package org.sunspotworld.demo;

import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ToneGenerator;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import java.util.Random;

import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import javax.microedition.midlet.MIDletStateChangeException;

import com.sun.spot.io.j2me.radiogram.RadiogramConnection;

import com.sun.spot.util.Utils;
/**
 *
 * @author noluckmurphy
 */
public class AudioThread implements Runnable {

        
    private EDemoBoard m_demo;
    private ToneGenerator m_toneGen;
    
    private static int m_Tones[] = {
        4545, 4290, 4050, 3822, 3608, 3405, 3214, 3034, 2863, 2703, 2551, 2408
    };

    
    private ITriColorLED [] m_leds;
    private static int m_major[] = { 0, 2, 4, 5, 7, 9, 11, 12 };
    private static int m_minor[] = { 0, 2, 3, 5, 7, 8, 10, 12 };
    private static int m_cded[] = { 0, 2, 4, 2 };
    private int m_notes[] = m_major;
    private String m_noteMode = "major";
    private int m_startValue = 0;
    private int m_startTempo = 1000;
    private int m_startRest = 80;
    private boolean m_useLog = false;
    private boolean m_useLightShow = false;
    private int m_typeInt=0;
 
    public AudioThread(int startValue, int startTempo, int startRest)
    {
        m_startValue = startValue;
        m_startTempo = startTempo;
        m_startRest = startRest;
        m_notes = m_major;
        m_demo = EDemoBoard.getInstance();
        m_leds = m_demo.getLEDs();
        m_typeInt = 0;
        m_toneGen = new ToneGenerator(m_demo.getIOPins()[EDemoBoard.D0]);
    }
    
    public void IsLogEnabled(boolean b)
    {
        m_useLog = b;
    }
    
    public void IsLightShowEnabled(boolean b)
    {
        m_useLightShow = b;
    }
    
    
    public void setStartPitch(int startValue)
    {
        m_startValue = startValue;
    }
    
    public void setStartTempo(int startTempo)
    {
        m_startTempo = startTempo;
    }
        
    public void setStartRest(int startRest)
    {
        m_startRest = startRest;
    }
    
    public void setScaleType(String s)
    {
        if(s.equals("major"))
        {
            m_notes = m_major;
            m_noteMode = "major";
        }
        else if(s.equals("minor"))
        {
            m_notes = m_minor;
            m_noteMode = "minor";
        }
        else
        {
            m_notes = m_cded;
            m_noteMode = "cded";
        }
    }
    
    public void toggleScaleType()
    {
        if(m_noteMode.equals("major"))
        {
            m_notes = m_minor;
            m_noteMode = "minor";
            m_typeInt =(m_typeInt +1 )%4;
        }
        else if(m_noteMode.equals("minor"))
        {
            m_notes = m_cded;
            m_noteMode = "cded";
            m_typeInt =(m_typeInt +1 )%4;
        }
        else if(m_noteMode.equals("cded")){
            m_notes = m_major;
            m_noteMode = "rand";
            m_typeInt =(m_typeInt +1 )%4;
        }
        else
        {
            m_notes = m_major;
            m_noteMode = "major";
            m_typeInt =(m_typeInt +1 )%4;
        }
    }
    
    public String getScaleType()
    {
        return m_noteMode;
    }
    
    public static int note2period(int note) {
        int octave = note / 12;
        return m_Tones[note % 12] / (1 << octave);
    }
    String recvNote(){
        String tmp = null;
        RadiogramConnection dgConnection = null;
        Datagram dg = null;

        try {
            dgConnection = (RadiogramConnection) Connector.open("radiogram://:37");
            // Then, we ask for a datagram with the maximum size allowed
            dg = dgConnection.newDatagram(dgConnection.getMaximumLength());
        } catch (IOException e) {
            System.out.println("Could not open radiogram receiver connection");
            e.printStackTrace();

        }

        while(true){
            try {
                dg.reset();
                dgConnection.receive(dg);
                tmp = dg.readUTF();
                int[] note = new int[4];

                int j =0;
                int k=0;
                for(int i =0; i<tmp.length(); i++){
                    if(tmp.charAt(i)==','){
                        note[k] = Integer.parseInt(tmp.substring(j, i-1));
                        j=i+1;
                        k++;
                        }
                }
                playNote(m_toneGen, note[0] + note[1], note[2], note[3], 0, 0, 0);
                System.out.println("Received: " + tmp + " from " + dg.getAddress());
            } catch (IOException e) {
                System.out.println("Nothing received");
            }
        }
    }
    void sendNote(int note, int dur, int len){
        DatagramConnection dgConnection = null;
        Datagram dg = null;
        try {
            // The Connection is a broadcast so we specify it in the creation string
            dgConnection = (DatagramConnection) Connector.open("radiogram://broadcast:37");
            // Then, we ask for a datagram with the maximum size allowed
            dg = dgConnection.newDatagram(dgConnection.getMaximumLength());
        } catch (IOException ex) {
            System.out.println("Could not open radiogram broadcast connection");
            ex.printStackTrace();
            return;
        }
        try {
            // We send the message (UTF encoded)
            dg.reset();
            dg.writeInt(note);
            dg.writeInt(dur);
            dg.writeInt(len);
            dg.writeInt(m_typeInt);
            dgConnection.send(dg);
            dgConnection.close();
            System.out.println("Broadcast is going through");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    void playNote(ToneGenerator tone, int note, int dur, int len, int nextNote, int nextTempo, int nextRest) {
        int on = dur * len/100;
        int first = dur - 230;
        tone.setPeriod(note2period(note));
        tone.setDuration(on);

        tone.beep();
        if(m_useLog)
        {
            System.out.println("note: " + Integer.toString(note) + " dur: " + 
                    Integer.toString(dur) + " len: " + Integer.toString(len) + " scale: " + m_noteMode);
        }
        
        try 
        {
            // This might not be right - if environment gets read while we're 
            // sleeping we might not finish the note.
            Thread.sleep(first);
            if(first<0){
                first =0;
            }
            sendNote(nextNote, nextTempo, nextRest);
            Thread.sleep(230);
        } 

        catch (InterruptedException e)
        {
            return;
        }
    }
       
    public void run()
    {
        int randint = 0;
        //if(spot.name == "Master"){
            Random r = new Random();
            randint = Math.abs(r.nextInt()) % m_notes.length;
        //    }
        int nextID =1;
        int nextNote =m_notes[nextID]+ m_startValue;;
        int nextTempo =m_startTempo;
        int nextRest = m_startRest;
        int thisID = 0;
        int thisNote = m_notes[thisID]+ m_startValue;
        int thisTempo = m_startTempo;
        int thisRest = m_startRest;
        while(true)
        {
                //if(name == "Master"){
                    randint = Math.abs(r.nextInt()) % m_notes.length;
                    // Play the tone, already
                    if(m_typeInt==3){
                        nextID = randint;
                    }
                    else{
                        nextID = (thisID +1)% m_notes.length;
                    }
                    nextNote = m_notes[nextID] + m_startValue;
                    nextTempo = m_startTempo;
                    nextRest = m_startRest;
                    
                    playNote(m_toneGen, thisNote, thisTempo, thisRest, nextNote, nextTempo, nextRest);
                    m_leds[thisID].setOff();
                    thisID = nextID;
                    thisNote = nextNote;
                    thisTempo = nextTempo;
                    thisRest = nextRest;
                 //   }
               //else{
                //    recvNote();
               //     }
                
                
                // Yay, pretty lights
                if(m_useLightShow)
                {
                    // TODO: Make this work w/o referencing m_notes[i] (will get 
                            // index outofbounds exception
                    
                    // Determine intensity from note level (higher = brighter)
                    // and dirtily "convert" it so that it is w/in [0 to 255]
                    //int brightness = (m_notes[i] + m_startValue) * 2;
                    //if(brightness > 255)
                    //    brightness = 255;
                    
                    //derka sherka
                    int brightness = (int) (m_startRest * 2.5);
               
                    // Turn on the lights!
                    m_leds[nextID].setOn();
                    
                    // Choose a color based on scale type
                    if(m_noteMode.equalsIgnoreCase("major"))
                        m_leds[nextID].setRGB(brightness, 0, 0);
                    else if(m_noteMode.equalsIgnoreCase("minor"))
                        m_leds[nextID].setRGB(0, 0, brightness);
                    else
                        m_leds[nextID].setRGB(0, brightness, 0);
                }
            
            
            /*if(m_useLightShow)
            {
                // clear the lights once we've played all the notes
                for(int i = 0; i < m_leds.length; i++)
                {
                    if(m_leds[i].isOn()){};
                }
            }*/
        }   
    }
}
